<?php


namespace app\common\lib;


use app\common\model\PushServer;
use app\common\model\UserPush;
use think\Log;
use think\queue\Job;
use XznsTools\cache\CacheManage;
use XznsTools\push\HuaweiV2 as Huawei;

class HwJob
{
    protected $pushTokenCacheModel = 'push_token'; //huawei=>5 xiaomi=>4 vivo=>3 oppo=>2 极光=> 1

    /**
     * 华为推送
     * @param Job $job
     * @param $jobData
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \think\exception\DbException
     */
    public function task1(Job $job, $jobData)
    {
        if ($job->attempts() > 1)
        {
            $job->delete();
        }
        try
        {
            Log::write(':华为推送开始:推送数据' . json_encode($jobData, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), 'log', true);
            $config = config('push.huawei');
            $hwPush = new Huawei($config);
            $token = $this->getAccessToke();

            $userPushModel = (new UserPush());
            $userPushModel = $userPushModel->whereIn('status', [0, 1])->where('push_type', 5);
            if ($jobData['hwPushType'] == 2)
            { // 标签推送
                $tag = explode(',', $jobData['tag']);
                $userPushModel->whereIn('version', $tag);
            }
            $totalNum = $userPushModel->group('regid')->count();
            $lastPage = (int)(ceil($totalNum / 3000));
            $page = 1;
            $pushNum = 0;
            do
            {
                $userPushModel = $userPushModel->whereIn('status', [0, 1])->where('push_type', 5);
                if ($jobData['hwPushType'] == 2)
                { // 标签推送
                    $tag = explode(',', $jobData['tag']);
                    $userPushModel->whereIn('version', $tag);
                }
                $regidData = $userPushModel->group('regid')->page($page, 3000)->column('regid');

                $num = count($regidData);
                for ($i = 0; $i < $num; $i += 1000)
                {
                    $regids = array_slice($regidData, $i, 1000);
                    try
                    {
                        $res = $hwPush->setData($jobData)->push($token, $regids);
                        if ($res['success'] && (int)$res['data']['code'] === 80200003)
                        {
                            $token = $this->getAccessToke(true);
                            $hwPush->setData($jobData)->push($token, $regids);
                        }
                    }
                    catch (\Exception $e)
                    {
                        Log::write('：华为推送失败：【' . json_encode($regids) . '】' . $e->getMessage(), 'error', true);
                    }
                }
                $pushNum += $num;// 推送总数
                $progress = sprintf('%.2f', $pushNum / $totalNum * 100);
                Log::write('华为推送' . $num . "条完成,进度{$progress}%,数量{$pushNum}/{$totalNum},总页数{$lastPage},当前页数{$page}：休息100毫秒", 'log', true);

                $page++;    // 下一页
                usleep(100000);
            } while ($lastPage >= $page);

            (new PushServer())->save(['is_huawei' => 1, 'huawei_push_num' => $pushNum], ['id' => $jobData['push_id']]);
        }
        catch (\Exception $e)
        {
            Log::write('华为推送异常：' . $e->getMessage() . '【' . $e->getFile() . $e->getLine() . '】', 'error');
            $totalNum = 0;
        }

        Log::write('华为推送结束：总数' . $totalNum, 'log', true);
        $job->delete();
    }

    /**
     * 获取accessToken
     * @param bool $isForce
     * @return array|bool|string
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \Exception
     */
    public function getAccessToke($isForce = false)
    {
        $token = '';
        if (!$isForce)
        {
            $token = CacheManage::getInstance()->setCacheConfig($this->pushTokenCacheModel, '5:v2')->getCache();
        }
        if (!$token)
        {
            $config = config('push.huawei');
            $hwPush = new Huawei($config);
            $tokenData = $hwPush->getAccessToken();
            $token = $tokenData['data']['access_token'];
            // token 写入缓存
            CacheManage::getInstance()->setCacheConfig($this->pushTokenCacheModel, '5:v2')->setCache($token, 'details', false);
        }

        return $token;
    }
}
